<?php
/**
 * Ruth Library
 * $Id: Catalog.php 2 2008-01-17 02:59:56Z baron314159@yahoo.com $
 *
 * LICENSE
 *
 * Copyright (c) 2007, Chris Utz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Impact Lab nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY CHRIS UTZ ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL CHRIS UTZ BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   Ruth
 * @package    Ruth_Message
 * @author     Chris Utz <chris@chrisutz.com>
 * @copyright  2007 Chris Utz <chris@chrisutz.com>
 * @license    http://www.opensource.org/licenses/bsd-license.php    New BSD License
 * @version    $Revision: 2 $
 */

/**
 * @see Ruth_Channel_Field
 */
require_once 'Ruth/Channel/Field.php';

/**
 * @see Ruth_ClassFactory
 */
require_once 'Ruth/ClassFactory.php';

/**
 * @see Ruth_Message_Exception
 */
require_once 'Ruth/Message/Exception.php';

/**
 * @see Ruth_Message_Generator
 */
require_once 'Ruth/Message/Generator.php';

/**
 * Holds validation error messages and provides a convienient interface for
 * generating html and other output in view scripts.
 *
 * @category   Ruth
 * @package    Ruth_Message
 * @author     Chris Utz <chris@chrisutz.com>
 * @copyright  2007 Chris Utz <chris@chrisutz.com>
 * @license    http://www.opensource.org/licenses/bsd-license.php    New BSD License
 * @version    $Revision: 2 $
 */
class Ruth_Message_Catalog
{
    /**
     * @var string
     */
    protected $_generatorClass = 'Ruth_Message_Generator';

    /**
     * @var array
     */
    protected $_tables = array();

    /**
     * @var string
     */
    protected $_defaultTableName = 'default';

    /**
     * @param string $className
     * @return Ruth_Message_Catalog
     */
    public function setMessageGeneratorClass($className)
    {
        $this->_generatorClass = $className;
        return $this;
    }

    /**
     * @return string
     */
    public function getMessageGeneratorClass()
    {
        return $this->_generatorClass;
    }

    /**
     * @param array $tables
     * @return Ruth_Message_Catalog
     */
    public function setTables(array $tables)
    {
        $this->_tables = $tables;
        return $this;
    }

    /**
     * @param string $tableName
     * @return Ruth_Message_Catalog
     */
    public function setDefaultTableName($tableName)
    {
        $this->_defaultTableName = $tableName;
        return $this;
    }

    /**
     * @return string
     */
    public function getDefaultTableName()
    {
        return $this->_defaultTableName;
    }

    /**
     * @param string $messageName
     * @param string|null $tableName
     * @param string|null $outputTemplate
     * @throws Ruth_Message_Exception
     */
    public function get($messageName, array $variables = array(), $tableName = null)
    {
        if (null === $tableName) {
            $tableName = $this->_defaultTableName;
        }

        $message = $this->_getMessage($messageName, $tableName);

        if (null === $message) {
            throw new Ruth_Message_Exception("message with name {$messageName} "
                . "in table {$tableName} does not exist or is invalid");
        }

        return $this->_instantiateGenerator($message, $variables);
    }

    /**
     * @param Ruth_Channel_Field $field
     * @param string|null $validatorName
     * @param string|null $messageName
     * @param string|null $tableName
     * @return string
     */
    public function getOnFailure(Ruth_Channel_Field $field, $validatorName = null, $messageName = null,
        $tableName = null)
    {
        if (null === $validatorName) {
            $validatorName = 'Valid';
        }

        if (null === $messageName) {
            $messageName = $field->getName() . '.' . $validatorName;
        }

        if (!$field->{'is' . $validatorName}) {
            if ($validatorName != 'Valid') {
                $options = $field->getValidator($validatorName)
                    ->getOptions()
                    ->getData();

                $specialVariables = array(
                    'name'  => $field->getNameFiltered(),
                    'value' => $field->__toString());

                $options = array_merge($options, $specialVariables);
            } else {
                $options = array();
            }

            return $this->get($messageName, $options, $tableName);
        } else {
            return '';
        }
    }

    /**
     * @param string $messageName
     * @param string $tableName
     */
    protected function _getMessage($messageName, $tableName)
    {
        if (!isset($this->_tables[$tableName])) {
            return null;
        }

        $table = &$this->_tables[$tableName];

        if (isset($table[$messageName])) {
            $messageInfo = $table[$messageName];

            if (is_string($messageInfo)) {
                return $messageInfo;
            } else if (is_array($messageInfo)) {
                if (isset($messageInfo['table'])) {
                    $refTable = $messageInfo['table'];
                } else {
                    $refTable = $tableName;
                }

                if (!isset($messageInfo['message'])) {
                    return null;
                } else {
                    $refMessage = $messageInfo['message'];
                }

                return $this->_getMessage($refMessage, $refTable);
            }
        }

        return null;
    }

    /**
     * 
     */
    protected function _instantiateGenerator($message, array $variables = array())
    {
        Ruth_ClassFactory::loadClass($this->_generatorClass);
        $class = new ReflectionClass($this->_generatorClass);

        if($class->getName() != 'Ruth_Message_Generator' and
            !$class->isSubclassOf(new ReflectionClass('Ruth_Message_Generator'))) {
            throw new Ruth_Message_Exception("_generatorClass is not a Ruth_Message_Generator");
        }

        return $class->newInstance($message, $variables);
    }
}
 
// vim: sw=4:ts=4:sts=4:et
